package com.ztrue.framework.handler;

import com.ztrue.framework.cache.CacheProvider;
import com.ztrue.framework.handler.definition.IHandlerDefinition;
import com.ztrue.common.utilities.Assert;
import com.ztrue.common.utilities.StringUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 表示一个简单的处理器注册表
 * 将通过缓存提高查询效率（通过处理目标查询时）
 *
 * @author zhangw
 * @date 2016/11/14 11:57
 * @version: 1.0
 */
public class SimpleHandlerDefinitionRegistry extends AbstractHandlerDefinitionRegistry {
    private final Map<String, IHandlerDefinition> handlerDefinitionMap = new ConcurrentHashMap<String, IHandlerDefinition>(64);


    /**
     * 使用此注册表注册一个新的处理器
     *
     * @param handlerName       处理器名称
     * @param handlerDefinition 处理器定义
     */
    @Override
    public void registerHandlerDefinition(String handlerName, IHandlerDefinition handlerDefinition) {
        Assert.hasText(handlerName, "[handlerName]不可为空");
        Assert.notNull(handlerDefinition, "处理器定于不可为空");
        this.handlerDefinitionMap.put(handlerName, handlerDefinition);
        CacheProvider.removeCache(CACHEGROUP, handlerDefinition.getHandlerTargetClassName());
    }

    /**
     * 移除一个处理器
     *
     * @param handlerName 处理器名称
     */
    @Override
    public void removeHandlerDefinition(String handlerName) throws NoSuchHandlerDefinitionException {
        IHandlerDefinition hd = this.handlerDefinitionMap.remove(handlerName);
        if (hd == null) {
            throw new NoSuchHandlerDefinitionException(handlerName);
        }
        CacheProvider.removeCache(CACHEGROUP, hd.getHandlerTargetClassName());
    }

    /**
     * 功过名称获取一个处理器
     *
     * @param handlerName 处理器名称
     * @return
     */
    @Override
    public IHandlerDefinition getHandlerDefinition(String handlerName) throws NoSuchHandlerDefinitionException {
        IHandlerDefinition handlerDefinition = this.handlerDefinitionMap.get(handlerName);
        if (handlerDefinition == null) {
            throw new NoSuchHandlerDefinitionException(handlerName);
        }
        return handlerDefinition;
    }

    /**
     * 根据处理器类型获取匹配的名称
     *
     * @param type
     * @return
     */
    @Override
    public String[] getHandlerNameByType(Class type) {
        List<String> matchs = new ArrayList<>();
        for (String handlerName :
                this.handlerDefinitionMap.keySet()) {
            if (type.isAssignableFrom(this.handlerDefinitionMap.get(handlerName).getHandlerClass())) {
                matchs.add(handlerName);
            }
        }
        return StringUtil.toStringArray(matchs);
    }

    /**
     * 判断一个处理器名称是否存在当前注册表
     *
     * @param handlerName 处理器名称
     * @return
     */
    @Override
    public boolean containsHandlerDefinition(String handlerName) {
        return this.handlerDefinitionMap.containsKey(handlerName);
    }

    /**
     * 获取当前注册表中所有处理器名称
     *
     * @return
     */
    @Override
    public String[] getHandlerDefinitionNames() {
        return StringUtil.toStringArray(this.handlerDefinitionMap.keySet());
    }

    /**
     * 获取当前注册表中注册的处理器数量
     *
     * @return
     */
    @Override
    public int getHandlerDefinitionCount() {
        return this.handlerDefinitionMap.size();
    }

    /**
     * 根据目标类型获取处理器名称
     *
     * @param targetType 目标类型
     * @return 处理器名称集合
     */
    @Override
    public String[] getHandlerNameByTargetType(Class targetType) {
        String[] hns = CacheProvider.<String[]>getCache(CACHEGROUP, targetType.getName());
        if (hns == null) {
            List<String> handlerNames = new ArrayList<>();
            for (String handlerName : handlerDefinitionMap.keySet()) {
                if (targetType.isAssignableFrom(handlerDefinitionMap.get(handlerName).getHandlerTargetClass())) {
                    handlerNames.add(handlerName);
                }
            }
            hns = StringUtil.toStringArray(handlerNames);
            CacheProvider.setCache(CACHEGROUP, targetType.getName(), hns, 1800);
        }
        return hns;
    }

    /**
     * 根据目标类型和处理器类型获取处理器名称
     *
     * @param targetType  目标类型
     * @param handlerType 处理器类型
     * @return
     */
    @Override
    public String[] getHandlerNameByTargetTypeAndHandlerType(Class targetType, Class handlerType) {
        String[] hns = CacheProvider.<String[]>getCache(CACHEGROUP, targetType.getName() + "_" + handlerType.getName());
        if (hns == null) {
            List<String> handlerNames = new ArrayList<>();
            IHandlerDefinition handlerDefinition;
            for (String handlerName : handlerDefinitionMap.keySet()) {
                handlerDefinition = handlerDefinitionMap.get(handlerName);
                if (targetType.isAssignableFrom(handlerDefinition.getHandlerTargetClass()) &&
                        handlerType.isAssignableFrom(handlerDefinition.getHandlerClass())) {
                    handlerNames.add(handlerName);
                }
            }
            hns = StringUtil.toStringArray(handlerNames);
            CacheProvider.setCache(CACHEGROUP, targetType.getName() + "_" + handlerType.getName(), hns, 1800);
        }
        return hns;
    }
}